package com.uuah.server.config.spring;

import java.io.IOException;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.AbstractXmlApplicationContext;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;

import com.uuah.server.api.IUuahContext;
import com.uuah.server.config.ConfigResource;
import com.uuah.utils.IOUtils;

public class UuahApplicationContext extends AbstractXmlApplicationContext {
	private IUuahContext uuahContext;
	private Resource[] springResources;

	public UuahApplicationContext(IUuahContext uuahContext,
			ConfigResource[] configResources) throws BeansException {
		this(uuahContext, convert(configResources));
	}

	public UuahApplicationContext(IUuahContext uuahContext,
			Resource[] springResources) throws BeansException {
		this.uuahContext = uuahContext;
		this.springResources = springResources;
	}

	protected void prepareBeanFactory(
			ConfigurableListableBeanFactory beanFactory) {
		super.prepareBeanFactory(beanFactory);
		beanFactory
				.addBeanPostProcessor(new UuahContextPostProcessor(uuahContext));
	}

	private static Resource[] convert(ConfigResource[] resources) {
		Resource[] configResources = new Resource[resources.length];
		for (int i = 0; i < resources.length; i++) {
			ConfigResource resource = resources[i];
			if (resource.getUrl() != null) {
				configResources[i] = new UrlResource(resource.getUrl());
			} else {
				try {
					configResources[i] = new ByteArrayResource(IOUtils
							.toByteArray(resource.getInputStream()), resource
							.getResourceName());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
		}
		return configResources;
	}

	protected Resource[] getConfigResources() {
		return springResources;
	}

	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
			throws IOException {
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(
				beanFactory);
		beanDefinitionReader
				.setDocumentReaderClass(UuahBeanDefinitionDocumentReader.class);
		beanDefinitionReader
				.setProblemReporter(new MissingParserProblemReporter());
		beanDefinitionReader.loadBeanDefinitions(springResources);
	}

	protected DefaultListableBeanFactory createBeanFactory() {
		DefaultListableBeanFactory bf = super.createBeanFactory();
		if (getParent() != null) {
			AbstractBeanFactory beanFactory = (AbstractBeanFactory) getParent()
					.getAutowireCapableBeanFactory();
			bf.copyConfigurationFrom(beanFactory);
		}
		return bf;
	}

}
